﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Three
{
    public static class JMath
    {
        public const double E = Math.E;
        public readonly static double LN10 = Math.Log(10,E);
        public readonly static double LN2 = Math.Log(2,E);
        public readonly static double LOG10E = Math.Log10(E);
        public readonly static double LOG2E = Math.Log(E,2);
        public const double PI = Math.PI;
        public readonly static double SQRT1_2 = Math.Sqrt(0.5);
        public readonly static double SQRT2 = Math.Sqrt(2);

        public static double abs(double x) =>Math.Abs(x);
        public static double acos(double x) => Math.Acos(x);
        public static double acosh(double x) => log(x+sqrt(x*x-1));
        public static double asin(double x) => Math.Asin(x);
        public static double asinh(double x) => log(x + sqrt(x * x + 1));
        public static double atan(double x) => Math.Atan(x);
        public static double atan2(double x, double y) =>Math.Atan2(x,y);
        public static double atanh(double x) =>log(1+x)/(1-x)/2;
        public static double cbrt() => 0;
        public static double ceil(double x) => Math.Ceiling(x);
        public static int clz32(int x) =>32-(int) log2(x);
        public static double cos(double x) => Math.Cos(x);
        public static double cosh(double x) => Math.Cosh(x);
        public static double exp(double x) => Math.Exp(x);
        public static double expm1(double x) => Math.Exp(x)-1;
        public static double floor(double x) => Math.Floor(x);
        //JavaScript中的Math.fround() 函数用于查找给定Number的最接近的32位单精度浮点表示形式
        public static float fround(double x) => (float)x;
        public static double hypot(params double[]values) => Math.Sqrt(values.Sum(v=>v*v));
        //Math.imul()函数用于计算作为参数传递给它的两个整数的32位乘法结果
        public static int imul(int x, int y) => (int)Math.BigMul(x,y);//
        public static double log(double x) => Math.Log(x);
        public static double log10(double x) => Math.Log10(x);
        public static double log1p(double x) =>Math.Log(1+x);
        public static double log2(double val) => Math.Log(val,2);
        public static double max(params double[] values) => values.Max();
        public static int max(params int[] values) => values.Max();
        public static double min(params double[] values) => values.Min();
        public static int min(params int[] values) => values.Min();
        public static double pow(double x, double y) => Math.Pow(x,y);
        private static Random _random=new Random();
        public static double random()
        {
            return _random.NextDouble();
        }
        public static double round(double x) => Math.Round(x);
        public static double sign(double x) => Math.Sign(x);
        public static double sin(double x) => Math.Sin(x);
        public static double sinh(double x) => Math.Sinh(x);
        public static double sqrt(double x) => Math.Sqrt(x);
        public static double tan(double x) => Math.Tan(x); 
        public static double tanh(double x) => Math.Tanh(x);
        public static double trunc(double x) => Math.Truncate(x);
        public static bool isFinite(double val) => double.IsInfinity(val);
        public static bool isFinite(float val) => float.IsInfinity(val);

        public static int add(int x, int y)
        {
            if (x == int.MaxValue || y == int.MaxValue || (int.MaxValue - x) <= y)
            {
                return int.MaxValue;
            }

            return x + y;
        }

        /// <summary>
        /// 正数相乘, 目前只考虑的两个值相乘大于int.MaxValue 的情况
        /// </summary>
        /// <param name="x"></param>
        /// <param name="scale"></param>
        /// <returns></returns>
        public static int multiply(int x, int scale)
        {
            if (x > 0 && scale > 0 && x * scale < 0)
            {
                return int.MaxValue;
            }
            if (x < 0 && scale < 0 && x * scale < 0)
            {
                return int.MaxValue;
            }
            return x * scale;
        }

        /// <summary>
        /// 模拟js中Date.now()
        /// </summary>
        /// <returns></returns>
        public static long dateNow()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000;
        }

        public static long performanceNow()
        {
            //performance.timing.navigationStart = 1680166452990;
            //js中Date.now() ≈ performance.timing.navigationStart + performance.now()
            return dateNow() - 1680166452990;
        }
    }
}